package ferp.core.mode;

import ferp.core.calc.Calculator;
import ferp.core.game.Game;
import ferp.core.game.Input;
import ferp.core.game.Settings;
import ferp.core.log.Log;
import ferp.core.player.Player;
import ferp.core.player.Profile;
import ferp.core.state.State;
import ferp.core.tutorial.Scenario;

/**
 * User: olegs
 * Date: 19/05/11 15:11
 */
public class Tricking extends TrickingBase
{
  @Override
  public int initialize(Game.Listener listener, Profile profile, Game g, Settings settings) throws Game.Error
  {
    // choose an appropriate mode depending on the game declared
    if (g.declarer() != g.human() && g.getBid(g.human().id()).current.isPass() && settings.skipGameOnPass)
    {
      g.set(State.fastMoving);

      return State.Result.SCHEDULE;
    }

    return super.initialize(listener, profile, g, settings);
  }

  @Override
  public Player mover(Game g, Settings settings, int current)
  {
    return g.isOpen() && current != g.player.declarer ? g.opponent() : super.mover(g, settings, current);
  }

  @Override
  public void score(Game g, Settings settings)
  {
    Calculator.get(settings.gameFlavor).tricking(g, settings);

    super.score(g, settings);
  }

  @Override
  public void mark(Game.Listener listener, Game g)
  {
    if (g.options.hand == 0)
      listener.markStand(g.scenario().stand());
    else
      super.mark(listener, g);
  }

  @Override
  protected int options(Game.Listener listener, Game g, Settings settings, Input input) throws Game.Error
  {
    if (g.type == Game.Type.UNKNOWN)
    {
      if (g.player.current == g.player.declarer)
        return super.options(listener, g, settings, input);

      return g.opponent().setStandInputOptions(g.options);
    }

    return super.options(listener, g, settings, input);
  }

  @Override
  protected Scenario.Note getOptionsNote(Game g, Settings settings)
  {
    if (g.type == Game.Type.UNKNOWN && g.player.current != g.player.declarer)
      return g.scenario().getGameTypeOptionsNote();

    return super.getOptionsNote(g, settings);
  }

  @Override
  protected boolean validate(Game.Listener listener, Game g, Settings settings, Input input)
  {
    if (input.card == 0)
    {
      boolean valid = input.stand == g.scenario().stand();

      if (!valid)
        listener.onInvalidGameType();

      return valid;
    }

    return super.validate(listener, g, settings, input);
  }

  @Override
  protected Act act(Game.Listener listener, Game g, Settings settings, Input input) throws Game.Error
  {
    if (g.rounds == 0 && g.player.current != g.player.declarer && g.type == Game.Type.UNKNOWN)
    {
      // set game's type according to an opponent decision
      g.opponent().setGameType(g, input);

      if (g.isOpen())
      {
        // open players' hands
        g.getOpponentHand().open = true;
        g.getPasserHand().open = true;

        listener.onOpenGameType(g, settings, g.opponent(), g.passer());
      }
      else
      {
        Log.debug(Log.TAG, "game type is standing, resetting resolver");

        if (g.whisters == 1 && g.passers == 1 && g.opponent() != g.human())
          listener.onStandingGameType();

        // fire event to prepare the tree for standing game type
        listener.onRecalculateOnNextSolveRequested(g.trick.current);
      }

      return Act.STAY;
    }

    return super.act(listener, g, settings, input);
  }
}
